package com.rds.common.utils.rds;

import com.rds.common.core.domain.AjaxResult;
import com.rds.common.core.domain.entity.DynamicVo;
import com.rds.common.core.service.IDynamicService;
import com.rds.common.utils.DateUtils;
import com.rds.common.utils.SecurityUtils;
import com.rds.common.utils.StringUtils;
import com.rds.common.utils.rds.HistoryRecordUtil;

import java.util.*;

/**
 *  此类主要用作生命周期相关操作
 *  @version : 1.0
 * @Copyright: Copyright(c) 2020-2021 All right reserved
 * @Company: GUANGZHOU RDS Co.,LTD
 * @author: LiChuanlong
 * @create Date : 2021/12/8 : 13:51
 */
public class LifecycleUtil {
    private IDynamicService dynamicService;

    public LifecycleUtil(IDynamicService dynamicService){
        this.dynamicService = dynamicService;
    }

    /**
     * 根据当前策略Id 查询所有的状态 并排序
     * @param policyId 策略id
     * @return 返回根据sort 排好序的状态Map
     */
    public Map<Integer,Long> listStateOrderBySort(Long policyId){
        DynamicVo dynamicVo=new DynamicVo();
        ArrayList<String> queryWrapper=new ArrayList<>();
        queryWrapper.add("and policyid="+policyId);
        dynamicVo.setQueryWrapper(queryWrapper);
        dynamicVo.setTableName("rda_policy");
        List<HashMap<String,Object>> stateList=dynamicService.selectList(dynamicVo);
        Map<Integer,Long> sortedStateMap = new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2 ;
            }
        });
        /*将查询到的State 按照sort 排序**/
        for(HashMap<String,Object> state : stateList){
            sortedStateMap.put((Integer) state.get("sort"),(Long) state.get("id"));
        }
        return sortedStateMap;
    }

    /**
     * 根据当前策略 自动升级及降级
     * @param policyId 策略id
     * @param event 事件(升级或降级)
     * @param currentSort 当前对象的状态对应的sort值
     * @return 返回成功后需要设置的状态Id 和提示信息
     */
    private Map<String,Object> goToTargetState(Long policyId,String event,int currentSort){
        Map<String,Object> messageMap = new HashMap<>();
//        LifecycleUtil lifecycleUtil = new LifecycleUtil(rdaStateService);
//        Map<Integer,Long> stateMap = lifecycleUtil.listStateOrderBySort(policyId);
        Map<Integer,Long> stateMap = listStateOrderBySort(policyId);
        Long targetStateId = -1L;
        if("promote".equalsIgnoreCase(event)){
            if(stateMap.containsKey(currentSort+1)){
                targetStateId = stateMap.get(currentSort+1);
                messageMap.put("code",0);
                messageMap.put("msg","提升成功!");
            }else{
                messageMap.put("code",-1);
                messageMap.put("msg","当前状态为终点状态,无法继续提升!");
            }
            messageMap.put("targetStateId",targetStateId);
        }  else if("demote".equalsIgnoreCase(event)){
            if(stateMap.containsKey(currentSort-1)){
                targetStateId = stateMap.get(currentSort-1);
                messageMap.put("code",0);
                messageMap.put("msg","降级成功!");
            }else{
                messageMap.put("code",-1);
                messageMap.put("msg","当前状态为初始状态,无法继续降级!");
            }
            messageMap.put("targetStateId",targetStateId);
        }
        return messageMap;
    }

    /**
     * 升级/降级到指定的状态
     * @param policyId 策略Id
     * @param event 提升/降级
     * @param currentSort 当前状态在整个策略中的索引
     * @param appointTargetStateId 指定提升或降级的状态Id 可以为空或0L
     * @return 返回成功后需要设置的状态Id 和提示信息
     */
    public Map<String,Object> goToAppointTargetState(Long policyId,String event,int currentSort,Long appointTargetStateId){
        if(appointTargetStateId == null || StringUtils.isBlank(String.valueOf(appointTargetStateId)) || appointTargetStateId == 0L){
            return goToTargetState(policyId,event,currentSort);
        } else {
            Map<String,Object> messageMap = new HashMap<>();
//            LifecycleUtil lifecycleUtil = new LifecycleUtil(rdaStateService);
//            Map<Integer,Long> stateMap = lifecycleUtil.listStateOrderBySort(policyId);
            Map<Integer,Long> stateMap = listStateOrderBySort(policyId);

            if(stateMap.containsValue(appointTargetStateId)){
                if("promote".equalsIgnoreCase(event)){
                    /*判断当前指定节点是否为终点节点**/
                    if(stateMap.containsKey(currentSort+1)){
                        messageMap.put("code",0);
                        messageMap.put("msg","提升成功!");
                    }else{
                        messageMap.put("code",-1);
                        messageMap.put("msg","当前状态为终点状态,无法继续提升!");
                    }
                }else if("demote".equalsIgnoreCase(event)){
                    /*判断当前指定节点是否为初始节点**/
                    if(stateMap.containsKey(currentSort-1)){
                        messageMap.put("code",0);
                        messageMap.put("msg","降级成功!");
                    }else{
                        messageMap.put("code",-1);
                        messageMap.put("msg","当前状态为初始状态,无法继续降级!");
                    }
                }
            }else{
                messageMap.put("code",-1);
                messageMap.put("msg","指定状态和策略不匹配,无法操作!");
            }
            messageMap.put("targetStateId",appointTargetStateId);
            return messageMap;
        }
    }


    /**
     * 区分模块分别对对象提升/降低生命周期操作
     * 如果后面需要新增对象类型进行生命周期操作 只需要加入else if 既可
     * @param id 当前对象Id
     * @param policyid 策略Id
     * @param event 提升/降级
     * @param moduleName 模块名称
     * @param workflow 是否是流程提升(默认是false;) 流程提升(传参数true)不需要判断权限
     * @return 提升信息
     */
    public AjaxResult goToTargetState(Long id, Long policyid, String event, String moduleName,boolean workflow){
        if ("document".equalsIgnoreCase(moduleName)) {
            Map<String, Object> document = dynamicService.selectDataById("rda_document",id);
            int currentStateId = (int) document.get("stateid");
            if(!workflow){
                /*判断权限*/
                if("demote".equals(event)){
                    if(SecurityUtils.verifyPermissions("demote", String.valueOf(currentStateId))) {
                        return AjaxResult.error( "您没有此状态的降级权限");
                    }
                }else{
                    if(SecurityUtils.verifyPermissions("promote", String.valueOf(currentStateId))) {
                        return AjaxResult.error( "您没有此状态的升级权限");
                    }
                }
            }
            //System.out.println("LifeCycleController:"+event+"--->>>currentStateId:" + currentStateId);
            /*获取当前策略下的所有状态**/
            Map<String, Object> eventMap = getToBeSetStateMap(policyid,currentStateId,event);
            if ("0".equals(String.valueOf(eventMap.get("code")))) {
                int targetStateId = parseString2Int(String.valueOf(eventMap.get("targetStateId")));
                Map<Integer,Long> stateMap = listStateOrderBySort(policyid);
                /*如果当前是非首次发布(升版后在发布),则第一版本必须废弃 2021-12-24 begin***/
                ObsoletePreObject(id,stateMap,targetStateId,moduleName);
                /*如果当前是非首次发布(升版后在发布),则第一版本必须废弃 2021-12-24 end***/

                //如果当前被设置的节点是发布 则需要设置发布时间;必须是提升时(此时这里发布节点必须是倒数第二个  否则这里的逻辑就不适应了)
                if(targetStateId == parseLong2Int(stateMap.get(stateMap.size() -1)) && "promote".equalsIgnoreCase(event)){
                    document.put("publish_time",DateUtils.getNowDate());
                }
                document.put("stateid",targetStateId);
                ArrayList<String> updateWrapper=new ArrayList<>();
                updateWrapper.add("id="+document.get("id"));
                int rows = dynamicService.updateData("rda_document",document,updateWrapper);
                new HistoryRecordUtil(dynamicService).lifeCycleHistory(id,currentStateId,targetStateId,event);
                return  rows > 0 ? AjaxResult.success((String) eventMap.get("msg")) : AjaxResult.error("提升失败!");
            } else if ("-1".equals(String.valueOf(eventMap.get("code")))) {
                return AjaxResult.error((String) eventMap.get("msg"));
            }else{
                return AjaxResult.error( "出现未知错误,请联系管理员!");
            }
        }else {
            return AjaxResult.success(event+"对象类型不存在,请联系管理员!");
        }
    }

    /**
     * 处理当前对象是否是提升/降级
     * @param policyid 策略Id
     * @param currentStateId 当前状态Id
     * @param event 提升/降级
     * @return 提升/降级 后的状态Id 集合
     */
    private Map<String, Object> getToBeSetStateMap(Long policyid,int currentStateId,String event){
        /*这里的sort 必须在创建状态的时候按照顺序来,即使是后面新增的状态,状态sort值也得修改 同一策略的状态sort 不能一样**/
        Long selectStateId = parseInt2Long(currentStateId);
        int currentSort = (int) dynamicService.selectDataById("rda_state",selectStateId).get("sort");
        /*获取当前策略下的所有状态**/
//        LifecycleUtil lifecycleUtil = new LifecycleUtil(dynamicService);
//        return lifecycleUtil.goToTargetState(policyid, event, currentSort);
        return goToTargetState(policyid, event, currentSort);
    }


    /**
     * 针对非首版对象发布时,将上一版本对象的状态设置为废弃
     * 仅限提升时
     * @param id 当前升版对象的Id
     * @param stateMap 状态Map
     * @param targetStateId 目标状态
     * @param moduleName 当前模块名称
     */
    public void ObsoletePreObject(Long id,Map<Integer,Long> stateMap,int targetStateId,String moduleName){
        //这里发布节点必须是倒数第二个  否则这里的逻辑就不适应了
        if(targetStateId == parseLong2Int(stateMap.get(stateMap.size() -1))){
            if("document".equalsIgnoreCase(moduleName)){
                /*如果是升版后的对象 此时recordId 必然会是上一版本的对象Id;如果是首版 则recordId 为空**/
                Long recordId = (Long) dynamicService.selectDataById("rda_document",id).get("record_id");
                if(!"null".equals(String.valueOf(recordId)) && String.valueOf(recordId) != null && !"".equals(String.valueOf(recordId))){
                    Map<String, Object> preDocument =  dynamicService.selectDataById("rda_document",recordId);
                    //将上一版本对象设置为生命周期的最后一个节点,通常就是废弃节点
                    Map<String, Object> data=new HashMap<>();
                    data.put("stateid",parseLong2Int(stateMap.get(stateMap.size())));
                    ArrayList<String> updateWrapper=new ArrayList<>();
                    updateWrapper.add("id="+preDocument.get("id"));
                    int rows = dynamicService.updateData("rda_document",data,updateWrapper);
                }

            }
        }
    }



    private Long parseInt2Long(int stateId){
        return Long.parseLong(String.valueOf(stateId));
    }

    private Integer parseString2Int(String stateId){
        return Integer.parseInt(stateId);
    }

    private Integer parseLong2Int(Long stateId){
        return Integer.parseInt(String.valueOf(stateId));
    }

    public String getStateName(int stateId){
        Long selectStateId = Long.parseLong(String.valueOf(stateId));
        return (String) dynamicService.selectDataById("rda_state",selectStateId).get("description");
    }

    /**
     * 添加历史记录(ES)
     * @param id 当前对象Id
     * @param currentStateId 当前状态Id
     * @param targetStateId  提升/降级后状态Id
     * @param operate 提升/降级
     * @param module 需更新对象(文档(document)、项目(project)、模板(template)、任务(wbs))
     */
    public void recordHistory(Long id,int currentStateId,int targetStateId,String operate,String module){
        String operation = "promote".equalsIgnoreCase(operate) ? "提升" : "demote".equalsIgnoreCase(operate) ? "降级" : "operate";
        StringBuilder historyBuilder = new StringBuilder();
        String oldStateName = getStateName(currentStateId);
        String newStateName = getStateName(targetStateId);
        /*加入操作记录**/
        historyBuilder.append("操作:"+operation).append(",状态由:" + oldStateName).append("-->" + newStateName).append(";");
        historyBuilder.append("操作者:" + SecurityUtils.getUsername()).append(";");
        historyBuilder.append("操作时间:" + DateUtils.DateToString(new Date()));
        //EsUtils.addHistory(sysElasticSearchMapper2, id, "生命周期-"+operation, historyBuilder.toString(), module);
    }
}
